package com.xdf.ecommerce.service.hystrix;

import com.alibaba.fastjson.JSON;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheKey;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheRemove;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
import com.xdf.ecommerce.service.NacosClientService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 注解的方式实现 Hystrix 请求缓存
 * @author chanchaw
 * @create 2025-10-30 15:39
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CacheHystrixCommandAnnotation {
    private final NacosClientService nacosClientService;

    //#region 第一种注解实现请求缓存的方法
    @HystrixCommand(commandKey = "CacheHystrixCommandAnnotation")
    @CacheResult(cacheKeyMethod = "getCacheKey")
    public List<ServiceInstance> useCache8Annotation01(String serviceId){
        List<ServiceInstance> ret = nacosClientService.getNacosClientInfo(serviceId);
        log.info("第一种方法优先从缓存获取数据，响应来的服务实例：[{}]，线程名称：[{}]", JSON.toJSONString(ret), Thread.currentThread().getName());
        return ret;
    }
    @HystrixCommand
    @CacheRemove(commandKey = "CacheHystrixCommandAnnotation", cacheKeyMethod = "getCacheKey")
    public void flushCache8Annotation01(String cacheId){
        log.info("通过注解清理 Hystrix 请求缓存数据，服务id:[{}]", cacheId);
    }

    /**
     * 获取缓存的 key，本方法签名必须和调用者方法函数签名一致
     * 即要和 useCache8Annotation01 的函数签名一致（参数数量，参数数据类型一致）
     * @param cacheId
     * @return
     */
    public String getCacheKey(String cacheId){
        return cacheId;
    }
    //#endregion

    //#region 第二种方式实现请求缓存
    /**
     * 传入参数使用了注解 @CacheKey
     * @param serviceId
     * @return
     */
    @CacheResult
    @HystrixCommand(commandKey = "CacheHystrixCommandAnnotation")
    public List<ServiceInstance> useCacheByAnnotation02(@CacheKey String serviceId){
        log.info("第二种方式实现请求缓存，服务id:[{}]", serviceId);
        return nacosClientService.getNacosClientInfo(serviceId);
    }

    @HystrixCommand
    @CacheRemove(commandKey = "CacheHystrixCommandAnnotation")
    public void flushCacheByAnnotation02(@CacheKey String cacheId){
        log.info("第二种方式清除请求缓存，cacheId:[{}]", cacheId);
    }
    //#endregion

    //#region 第三种方式，在第二种方式的基础上去掉注解 @CacheKey...
    // 则 Hystrix 将参数列表中的所有参数作为 cacheId，类似的
    // 清除缓存的方法也是将所有参数的列表联合作为 cacheId
    // 所以第三种方式其实就是第二种方式
    /**
     * 传入参数使用了注解 @CacheKey
     * @param serviceId
     * @return
     */
    @CacheResult
    @HystrixCommand(commandKey = "CacheHystrixCommandAnnotation")
    public List<ServiceInstance> useCacheByAnnotation03(String serviceId){
        log.info("第二种方式实现请求缓存，服务id:[{}]", serviceId);
        return nacosClientService.getNacosClientInfo(serviceId);
    }

    @HystrixCommand
    @CacheRemove(commandKey = "CacheHystrixCommandAnnotation")
    public void flushCacheByAnnotation03(String cacheId){
        log.info("第二种方式清除请求缓存，cacheId:[{}]", cacheId);
    }
    //#endregion

    //#region 总结：实际工作中一般使用第二种方法
    //#endregion
}
